package org.dromara.common.heweather.jwt;

import com.alibaba.fastjson2.JSON;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Duration;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * 和风天气 JWT 生成
 * @Author: Stars
 * @Date: 2025/4/4 14:15
 */
public class JwtHefengApi {

    /**
     * jwt 私钥
     */
    private static String privateKeyString = "MC4CAQAwBQYDK2VwBCIEIIyFBt3Upb1x9gTpqONCMXGq5URV+THGVXNfg2Jk+4wP";

    /**
     * jwt缓存key
     *
     */
    private static final String HEWEATHER_JWT_CACHE_KEY = "heweather_jwt_cache_key";

    public static String getJwt() {
        // 获取缓存中的jwt
        String cacheJwt = RedisUtils.getCacheObject(HEWEATHER_JWT_CACHE_KEY);
        if (StringUtils.isNotEmpty(cacheJwt)){
            return cacheJwt;
        }
        try {
           // Private key
           privateKeyString = privateKeyString.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").trim();
           byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
           PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
           KeyFactory keyFactory = KeyFactory.getInstance("EdDSA");
           PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

           // Header
           Map<String,String> headerMap = new HashMap<>();
           headerMap.put("alg", "EdDSA");
           headerMap.put("kid", "TCWH9PWEG7");
           String headerJson = JSON.toJSONString(headerMap);

           // Payload
           long iat = ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond() - 30;
           // 24小时，也是和风天气支持的最长时间
           long exp = iat + 24 * 60 * 60;
           Map<String,Object> payloadMap = new HashMap<>();
           payloadMap.put("sub", "4AKUWFYRBN");
           payloadMap.put("iat", iat);
           payloadMap.put("exp", exp);
           String payloadJson = JSON.toJSONString(payloadMap);

           // Base64url header+payload
           String headerEncoded = Base64.getUrlEncoder().encodeToString(headerJson.getBytes(StandardCharsets.UTF_8));
           String payloadEncoded = Base64.getUrlEncoder().encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
           String data = headerEncoded + "." + payloadEncoded;

           // Sign
           Signature signer = Signature.getInstance("EdDSA");
           signer.initSign(privateKey);
           signer.update(data.getBytes(StandardCharsets.UTF_8));
           byte[] signature = signer.sign();

           String signatureEncoded = Base64.getUrlEncoder().encodeToString(signature);

           String jwt = data + "." + signatureEncoded;
           // 缓存23小时，流一个小时的空挡，避免jwt失效
           RedisUtils.setCacheObject(HEWEATHER_JWT_CACHE_KEY,jwt, Duration.ofHours(23));
//        // Print Token
//        System.out.println("Signature:\n" + signatureEncoded);
//        System.out.println("JWT:\n" + jwt);
           return jwt;
       }catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException |SignatureException e){
           throw new RuntimeException("生成jwt失败");
       }
    }

    public static void main(String[] args) {
        System.out.println(getJwt());
    }
}
